package com.ddwl.goods.service.retail;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.ddwl.common.constant.*;
import com.ddwl.common.exception.CommonException;
import com.ddwl.common.exception.ExceptionCode;
import com.ddwl.common.exception.IllegalException;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.GateApi;
import com.ddwl.common.feign.api.MessageApi;
import com.ddwl.common.feign.api.SearchApi;
import com.ddwl.common.feign.api.ShopApi;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.MySqlUtil;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.goods.dao.*;
import com.ddwl.goods.dao.model.*;
import com.ddwl.goods.dto.ShoppingCarItemNumDto;
import com.ddwl.goods.mapper.ItemAgentMapper;
import com.ddwl.goods.model.*;
import com.ddwl.goods.service.GoodsProfitService;
import com.ddwl.goods.service.LimitTimePurActiveService;
import com.ddwl.goods.service.ShopGoodsProfitService;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.distr.SetGoodsProfitBo;
import com.ddwl.schema.bo.goods.ItemMediaBo;
import com.ddwl.schema.bo.goods.ItemShelfBo;
import com.ddwl.schema.bo.goods.QueryLimitTimePurGoodBo;
import com.ddwl.schema.bo.goods.SkuBo;
import com.ddwl.schema.bo.goods.retail.*;
import com.ddwl.schema.bo.message.ShopMessageBo;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.base.RestVo;
import com.ddwl.schema.vo.goods.*;
import com.ddwl.schema.vo.goods.retail.*;
import com.ddwl.schema.vo.shop.ShopVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author hemiaojun
 * @Date 2020/12/1 15:54
 */
@Service
@RequiredArgsConstructor
public class ShopItemService {

    private final ItemDao itemDao;
    private final CategoryDao categoryDao;
    private final SkuDao skuDao;
    private final ItemMediaDao itemMediaDao;
    private final ShoppingCartDao shoppingCartDao;
    private final SearchApi searchApi;
    private final ShopApi shopApi;
    private final MessageApi messageApi;
    private final ShopGoodsProfitService shopGoodsProfitService;
    private final GoodsProfitService goodsProfitService;
    private final DiscountItemDao discountItemDao;
    private final ItemTagDao itemTagDao;
    private final DiscountItemSkuDao discountItemSkuDao;
    private final LimitTimePurActiveService limitTimePurActiveService;
    private final LimitTimePurActiveDao limitTimePurActiveDao;
    private final LimitTimePurGoodDao limitTimePurGoodDao;
    private final ItemAgentMapper itemAgentMapper;
    private final GateApi gateApi;

    @Transactional(rollbackFor = Exception.class)
    public void createShopItem(ShopItemAddBo bo) {
        if (GoodsEnum.SkuTypeEnum.SINGLE.getCode().equals(bo.getSkuType())) {
            ParamException.isNull(bo.getStock(), "商品库存不能为空");
        }
        Item entity = BeanConverUtils.convertBean(bo, Item.class);
        fillItemInfo(entity, bo.getCategoryId(), bo.getMedias());
        entity.setBarcode(initBarCode(entity.getShopId(), entity.getCategoryId(), entity.getBarcode()));
        entity.setItemType(GoodsEnum.CategoryTypeEnum.RETAIL.getCode());
        barCodeAddUnique(entity, bo.getSkus());
        if (bo.getSales() == null) {
            entity.setSales(0);
        }
        entity.setFalseSales(0);
        entity.setId(UUIDGenerator.getShortUUID());
        entity.setItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        if (bo.getItemSort() == null) {
            entity.setItemSort(0);
        }
        entity.setSumSales(0);
        //获取佣金 商品佣金没有则取类目佣金 都有则取商品佣金
        GoodsProfit gp = calculateGoodsProfit(bo.getGoodsProfitBo(), bo.getCategoryId(), entity);
        //创建或更新子商品
        if (!CollectionUtils.isEmpty(bo.getSkus())) {
            entity.setSkuNum(bo.getSkus().size());
            createSku(bo.getSkus(), entity, gp);
        } else {
            entity.setSkuNum(1);
            initSku(entity);
            entity.setAttributeList("{\"规格\":[\"默认\"]}");
        }
        //创建或更新媒体
        if (!CollectionUtils.isEmpty(bo.getMedias())) {
            createAndUpdateMedias(bo.getMedias(), bo.getItemVideo(), entity.getId());
        }
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(entity.getHotFlag())) {
            saveItemTag(entity.getId(), GoodsEnum.ItemTagEnum.HOT_SELL.getCode(), GoodsEnum.ItemTagEnum.HOT_SELL.getName());
        }
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(entity.getLimitFlag())) {
            saveItemTag(entity.getId(), GoodsEnum.ItemTagEnum.LIMITED_BUY.getCode(), GoodsEnum.ItemTagEnum.LIMITED_BUY.getName());
        }
        entity.setAgencyFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        entity.setDiscountFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        entity.setLimitTimeFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        entity.setItemSgin(getItemTagString(entity.getId()));
        entity.setWxaCode(getWxaCodeOSSUrl(entity.getId()));
        itemDao.insert(entity);
        //设置佣金
        shopGoodsProfitService.setItemProfit(bo.getGoodsProfitBo(), entity.getId(), bo.getShopId());
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateShopItem(ShopItemUpdateBo bo) {
        if (GoodsEnum.SkuTypeEnum.SINGLE.getCode().equals(bo.getSkuType())) {
            ParamException.isNull(bo.getStock(), "商品库存不能为空");
        }
        Item item = itemDao.selectByPrimaryKey(bo.getId());
        ParamException.isTrue(BaseEnum.StatusEnum.ENABLE.getCode().equals(item.getDiscountFlag()), "该商品已经参加打折活动，不能修改");
        ParamException.isTrue(BaseEnum.StatusEnum.ENABLE.getCode().equals(item.getLimitTimeFlag()), "该商品已经参加限时购活动，不能修改");
        Integer oldSkuType = item.getSkuType();
        Item entity = BeanConverUtils.convertBean(bo, Item.class);
        fillItemInfo(entity, bo.getCategoryId(), bo.getMedias());
        if (BaseEnum.StatusEnum.DISABLE.getCode().equals(entity.getItemStatus())) {
            //条码判断是否重复
            barCodeUpdateUnique(bo.getId(), bo.getSkus());
        } else {
            throw new CommonException(ExceptionCode.SHELF_GOODS);
        }
        //获取佣金 商品佣金没有则取类目佣金 都有则取商品佣金
        GoodsProfit gp = calculateGoodsProfit(bo.getGoodsProfitBo(), bo.getCategoryId(), entity);
        //创建或更新子商品
        if (!CollectionUtils.isEmpty(bo.getSkus())) {
            item.setSkuNum(bo.getSkus().size());
            item.setSkuType(GoodsEnum.SkuTypeEnum.MULTIPLE.getCode());
            updateSku(bo.getSkus(), entity, gp);
        } else {
            updateSingleSku(entity, oldSkuType);
            item.setSkuType(GoodsEnum.SkuTypeEnum.SINGLE.getCode());
            item.setSkuNum(1);
            item.setAttributeList("{\"规格\":[\"默认\"]}");
        }
        //创建或更新媒体
        if (!CollectionUtils.isEmpty(bo.getMedias())) {
            createAndUpdateMedias(bo.getMedias(), bo.getItemVideo(), entity.getId());
        }
        item.setId(entity.getId());
        item.setCategoryCode(entity.getCategoryCode());
        item.setSupplierId(entity.getSupplierId());
        item.setItemImage(entity.getItemImage());
        item.setItemName(entity.getItemName());
        //item.setBarcode(entity.getBarcode());
        item.setRetailPrice(entity.getRetailPrice());
        item.setVipPrice(entity.getVipPrice());
        item.setOriginPrice(entity.getOriginPrice());
        item.setStock(entity.getStock());
        item.setCategoryId(entity.getCategoryId());
        item.setParamDetail(entity.getParamDetail());
        item.setItemDesc(entity.getItemDesc());
        item.setItemSort(entity.getItemSort());
        item.setHotFlag(entity.getHotFlag());
        item.setLimitFlag(entity.getLimitFlag());
        item.setLimitQuantity(entity.getLimitQuantity());
        //只有当sku不为空且AttributeList 有值时才进行赋值
        updateHotTag(item.getId(), item.getHotFlag());
        updateLimitBuyTag(item.getId(), item.getLimitFlag());
        item.setItemSgin(getItemTagString(item.getId()));
        item.setRecommend(entity.getRecommend());
        if (StrUtil.isNotBlank(entity.getAttributeList()) && !CollectionUtils.isEmpty(bo.getSkus())) {
            item.setAttributeList(entity.getAttributeList());
        }
        item.setItemCommission(entity.getItemCommission());
        itemDao.updateItem(item);
        shopGoodsProfitService.setItemProfit(bo.getGoodsProfitBo(), entity.getId(), bo.getShopId());
    }

    public String getWxaCodeOSSUrl(String itemId) {
        RestVo<String> stringRestVo = gateApi.wxaCodeUnlimit(itemId, BaseEnum.WxAppId.WBM.getCode(), String.format(GateEnum.WxaPath.ITEM_WXA_CODE.getPath(), itemId), GateEnum.WbmMinAppPage.ITEM_INDEX.getPath());
        if (StrUtil.isEmpty(stringRestVo.getResult())) {
            return null;
        }
        return stringRestVo.getResult();
    }

    private void updateHotTag(String itemId, Integer tagFlag) {
        updateTag(itemId, tagFlag, GoodsEnum.ItemTagEnum.HOT_SELL.getCode(), GoodsEnum.ItemTagEnum.HOT_SELL.getName());
    }

    private void updateLimitBuyTag(String itemId, Integer tagFlag) {
        updateTag(itemId, tagFlag, GoodsEnum.ItemTagEnum.LIMITED_BUY.getCode(), GoodsEnum.ItemTagEnum.LIMITED_BUY.getName());
    }

    private void updateTag(String itemId, Integer tagFlag, String tagCode, String tagName) {
        ItemTag itemTag = itemTagDao.getByItemIdAndCode(itemId, tagCode);
        if (null == itemTag && BaseEnum.StatusEnum.ENABLE.getCode().equals(tagFlag)) {
            saveItemTag(itemId, tagCode, tagName);
        }
        if (null != itemTag && BaseEnum.StatusEnum.DISABLE.getCode().equals(tagFlag)) {
            itemTagDao.deleteByItemIdAndCode(itemId, tagCode);
        }
    }

    private void saveItemTag(String itemId, String tagCode, String tagName) {
        ItemTag it = new ItemTag();
        it.setItemId(itemId);
        it.setCode(tagCode);
        it.setName(tagName);
        itemTagDao.insert(it);
    }

    private GoodsProfit calculateGoodsProfit(SetGoodsProfitBo goodsProfitBo, String categoryId, Item entity) {
        GoodsProfit gp = null;
        if (goodsProfitBo == null) {
            /*GoodsProfit goodsProfit = new GoodsProfit();
            goodsProfit.setTargetId(categoryId);
            goodsProfit.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
            gp = shopGoodsProfitService.selectOne(goodsProfit);
            if (gp != null) {
                //0是百分比 1是固定金额
                if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
                    entity.setItemCommission(entity.getRetailPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                }
                if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
                    entity.setItemCommission(gp.getRatio());
                }
            }else{
                entity.setItemCommission(BigDecimal.ZERO);
            }*/
            entity.setItemCommission(BigDecimal.ZERO);
        } else {
            gp = BeanConverUtils.convertBean(goodsProfitBo, GoodsProfit.class);
            entity.setItemCommission(getCommission(entity.getRetailPrice(), goodsProfitBo));
        }
        return gp;
    }

    /**
     * 获取当前佣金
     */
    public BigDecimal getCommission(BigDecimal price, SetGoodsProfitBo gp) {
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(gp.getStatus())) {
            if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
                return price.multiply(gp.getRatio()).divide(new BigDecimal(100));
            }
            if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
                ParamException.isTrue(gp.getRatio().compareTo(price) > 0, "分佣金额不能大于实际售价");
                return gp.getRatio();
            }
        }
        return BigDecimal.ZERO;
    }

    private void initSku(Item entity) {
        Sku sku = new Sku();
        sku.setBarcode(initBarCode(entity.getShopId(), entity.getId(), null));
        sku.setItemId(entity.getId());
        sku.setRetailPrice(entity.getRetailPrice());
        if (null != entity.getOriginPrice()) {
            sku.setRetailPrice(entity.getOriginPrice());
        }
        sku.setItemCommission(entity.getItemCommission());
        sku.setSkuStatus(1);
        sku.setLockStock(0);
        sku.setIndexNum(0);
        sku.setStock(entity.getStock());
        sku.setItemSpecs("{\"规格\":\"默认\"}");
        sku.setImageUrl(entity.getItemImage());
        skuDao.insert(sku);
    }

    /**
     * 新增判断商品条码和sku编码不能重复
     *
     * @param entity
     * @param skus
     */
    void barCodeAddUnique(Item entity, List<SkuBo> skus) {
        if (StrUtil.isNotEmpty(entity.getBarcode())) {
            Item item = new Item();
            item.setBarcode(entity.getBarcode());
            //商品条码不可重复录入
            if (!itemDao.select(item).isEmpty()) {
                entity.setBarcode(initBarCode(entity.getShopId(), entity.getCategoryId(), ""));
//                throw new CommonException(ExceptionCode.ITEM_BARCODE_EXISTS);
            }
        } else {
            entity.setBarcode(initBarCode(entity.getShopId(), entity.getCategoryId(), ""));
        }
        //sku编码不可重复录入
        //checkSkuUnique(skus);
    }

    private String initBarCode(String prefix, String mid, String barCode) {
        StringBuffer code = new StringBuffer();
        if (StrUtil.isNotEmpty(prefix)) {
            if (prefix.length() > 4) {
                code.append(prefix.substring(prefix.length() - 4).toUpperCase());
            } else {
                code.append(prefix.toUpperCase());
            }
        }
        if (StrUtil.isNotEmpty(mid)) {
            if (mid.length() > 3) {
                code.append(mid.substring(mid.length() - 3).toUpperCase());
            } else {
                code.append(mid.toUpperCase());
            }
        }
        if (StrUtil.isEmpty(barCode)) {
            code.append(RandomUtil.randomString(RandomUtil.BASE_CHAR, 4).toUpperCase()).append(RandomUtil.randomNumbers(3));
            return code.toString();
        }
        return code.append(barCode).toString();
    }

    /**
     * 修改判断商品条码和sku编码不能重复
     *
     * @param itemId
     * @param skus
     */
    void barCodeUpdateUnique(String itemId, List<SkuBo> skus) {
        //sku编码不可重复录入
        if (!CollectionUtils.isEmpty(skus)) {
            skuDao.deleteByItemId(itemId);
        }
    }

    /**
     * 创建更新媒体
     *
     * @param mediaList
     * @param itemVideo
     * @param itemId
     */
    void createAndUpdateMedias(List<ItemMediaBo> mediaList, String itemVideo, String itemId) {
        itemMediaDao.deleteByItem(itemId);
        if (StrUtil.isNotEmpty(itemVideo)) {
            ItemMedia media = new ItemMedia();
            media.setItemId(itemId);
            media.setId(UUIDGenerator.getShortUUID());
            media.setMediaIndex(0);
            media.setMediaUrl(itemVideo);
            media.setMediaType(1);
            itemMediaDao.insert(media);
        }
        for (ItemMediaBo itemMediaBo : mediaList) {
            ItemMedia media = new ItemMedia();
            BeanUtils.copyProperties(itemMediaBo, media);
            media.setItemId(itemId);
            media.setId(UUIDGenerator.getShortUUID());
            itemMediaDao.insert(media);
        }
    }

    /**
     * 创建子商品
     *
     * @param skuBoList
     * @param entity
     * @param gp
     */
    public void createSku(List<SkuBo> skuBoList, Item entity, GoodsProfit gp) {
        int index = 0;
        String itemId = entity.getId();
        String itemImage = entity.getItemImage();
        AtomicInteger stock = new AtomicInteger(0);
        for (SkuBo skuBo : skuBoList) {
            String skuCode = skuBo.getBarcode();
            if (checkSkuCode(skuCode)) {
                skuBo.setBarcode(initBarCode(entity.getShopId(), entity.getId(), skuCode));
            }
            if (StrUtil.isEmpty(skuBo.getImageUrl())) {
                skuBo.setImageUrl(itemImage);
            }
            if (gp != null && BaseEnum.StatusEnum.ENABLE.getCode().equals(gp.getStatus())) {
                //0是百分比 1是固定金额
                if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
                    if (null != skuBo.getFactoryPrice() && skuBo.getFactoryPrice().compareTo(BigDecimal.ZERO) > 0) {
                        skuBo.setItemCommission(skuBo.getFactoryPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                    } else {
                        skuBo.setItemCommission(skuBo.getRetailPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                    }
                }
                if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
                    if (null != skuBo.getFactoryPrice() && skuBo.getFactoryPrice().compareTo(BigDecimal.ZERO) > 0) {
                        ParamException.isTrue(gp.getRatio().compareTo(skuBo.getFactoryPrice()) > 0, "分佣金额不能大于子商品实际售价");
                    } else {
                        ParamException.isTrue(gp.getRatio().compareTo(skuBo.getRetailPrice()) > 0, "分佣金额不能大于子商品实际售价");
                    }
                    skuBo.setItemCommission(gp.getRatio());
                }
            }
            index = insertSku(index, itemId, skuBo);
            stock.addAndGet(skuBo.getStock());
        }
        entity.setStock(stock.get());
    }

    /**
     * 更新子商品
     *
     * @param skuBoList
     * @param entity
     * @param gp
     */
    public void updateSku(List<SkuBo> skuBoList, Item entity, GoodsProfit gp) {
        int index = 0;
        String itemId = entity.getId();
        String itemImage = entity.getItemImage();
        AtomicInteger stock = new AtomicInteger(0);
        for (SkuBo skuBo : skuBoList) {
            String skuCode = skuBo.getBarcode();
            if (checkSkuCode(skuCode)) {
                skuBo.setBarcode(initBarCode(entity.getShopId(), entity.getId(), ""));
            }
            if (StrUtil.isEmpty(skuBo.getImageUrl())) {
                skuBo.setImageUrl(itemImage);
            }
            if (gp != null && BaseEnum.StatusEnum.ENABLE.getCode().equals(gp.getStatus())) {
                //0是百分比 1是固定金额
                if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
                    if (null != skuBo.getFactoryPrice() && skuBo.getFactoryPrice().compareTo(BigDecimal.ZERO) > 0) {
                        skuBo.setItemCommission(skuBo.getFactoryPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                    } else {
                        skuBo.setItemCommission(skuBo.getRetailPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                    }
                }
                if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
                    if (null != skuBo.getFactoryPrice() && skuBo.getFactoryPrice().compareTo(BigDecimal.ZERO) > 0) {
                        ParamException.isTrue(gp.getRatio().compareTo(skuBo.getFactoryPrice()) > 0, "分佣金额不能大于子商品实际售价");
                    } else {
                        ParamException.isTrue(gp.getRatio().compareTo(skuBo.getRetailPrice()) > 0, "分佣金额不能大于子商品实际售价");
                    }
                    skuBo.setItemCommission(gp.getRatio());
                }
            } else {
                skuBo.setItemCommission(BigDecimal.ZERO);
            }
            index = insertSku(index, itemId, skuBo);
            stock.addAndGet(skuBo.getStock());
        }
        entity.setStock(stock.get());
    }

    private boolean checkSkuCode(String skuCode) {
        if (StrUtil.isNotEmpty(skuCode)) {
            Sku sku = new Sku();
            sku.setBarcode(skuCode);
            return !skuDao.select(sku).isEmpty();
        }
        return Boolean.TRUE;
    }

    private int insertSku(int index, String itemId, SkuBo skuBo) {
        Sku sku = new Sku();
        BeanUtils.copyProperties(skuBo, sku);
        sku.setId(UUIDGenerator.getShortUUID());
        sku.setItemId(itemId);
        sku.setDflag(0);
        sku.setSkuStatus(1);
        sku.setLockStock(0);
        sku.setIndexNum(index++);
        skuDao.insert(sku);
        return index;
    }

    private void updateSingleSku(Item entity, Integer oldSkuType) {
        if (GoodsEnum.SkuTypeEnum.SINGLE.getCode().equals(oldSkuType)) {
            BigDecimal retailPrice = entity.getRetailPrice();
            if (null != entity.getOriginPrice()) {
                retailPrice = entity.getOriginPrice();
            }
            skuDao.updateByItemId(entity.getId(), entity.getStock(), retailPrice, entity.getItemCommission());
        } else {
            skuDao.deleteByItemId(entity.getId());
            initSku(entity);
        }
    }

    private void fillItemInfo(Item entity, String categoryId, List<ItemMediaBo> medias) {
        //添加供应商id
        if (StringUtils.hasText(categoryId)) {
            Category category = categoryDao.selectByPrimaryKey(categoryId);
            entity.setCategoryCode(category.getCategoryCode());
            entity.setSupplierId(category.getSupplierId());
        }
        //获取商品列表主图
        for (ItemMediaBo itemMediaBo : medias) {
            if (itemMediaBo.getMediaIndex() == 1) {
                entity.setItemImage(itemMediaBo.getMediaUrl());
            }
        }
    }

    /**
     * 首页商品列表
     *
     * @param pageBo
     * @return
     */
    public PageVo<ShopItemListVo> list(PageBo<ShopItemListBo> pageBo) {
        ShopItemListBo param = pageBo.getParam();
        PageVo pageVo = new PageVo();
        pageVo.setPage(pageBo.getPage());
        pageVo.setSize(pageBo.getPageSize());
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        Page<Item> pageInfo = (Page<Item>) itemDao.getList(param);
        List<Item> items = pageInfo.getResult();
        pageVo.setTotal(pageInfo.getTotal());
        List<String> agentItemIds;
        if (pageBo.getPage() == 1) {
            agentItemIds = itemAgentMapper.selectItemIdByShop(pageBo.getParam().getShopId());
            pageVo.setTotal(pageVo.getTotal() + 1);
        } else {
            agentItemIds = new ArrayList<>(0);
        }
        if (CollectionUtils.isEmpty(items)) {
            if (!agentItemIds.isEmpty()) {
                List<Item> agentItems = itemDao.selectByPrimaryKeys(agentItemIds);
                // 限时购
                List<String> limitTimePurItemIds = items.stream().filter(item -> BaseEnum.StatusEnum.ENABLE.getCode().equals(item.getLimitTimeFlag())).map(Item::getId).collect(Collectors.toList());
                Map<String, LimitTimePurItemVo> limitTimePurItemMap;
                if (!limitTimePurItemIds.isEmpty()) {
                    QueryLimitTimePurGoodBo limitTimePurBo = new QueryLimitTimePurGoodBo();
                    limitTimePurBo.setItemIds(limitTimePurItemIds);
                    List<LimitTimePurItemVo> limitTimePurItems = limitTimePurActiveService.getGood(limitTimePurBo);
                    limitTimePurItemMap = limitTimePurItems.stream().collect(Collectors.toMap(LimitTimePurItemVo::getItemId, Function.identity()));
                } else {
                    limitTimePurItemMap = new HashMap<>(0);
                }
                Map<String, Integer> shopCartItemQtyMap;
                if (StringUtils.hasText(param.getUserId())) {
                    List<ShoppingCarItemNumDto> shopCartItems = shoppingCartDao.getItemNumGroupByItem(param.getUserId(), agentItemIds);
                    shopCartItemQtyMap = shopCartItems.stream().collect(Collectors.toMap(ShoppingCarItemNumDto::getItemId, ShoppingCarItemNumDto::getExistNum));
                } else {
                    shopCartItemQtyMap = new HashMap<>(0);
                }
                pageVo.setData(agentItems.stream().map(item -> {
                    ShopItemListVo shopItemVo = BeanConverUtils.convertBean(item, ShopItemListVo.class);
                    shopItemVo.setExistCarNum(shopCartItemQtyMap.get(item.getId()));
                    LimitTimePurItemVo limitTimePurItem = limitTimePurItemMap.get(item.getId());
                    if (limitTimePurItem != null) {
                        LimitTimePurItemDetailVo detailVo = BeanConverUtils.convertBean(limitTimePurItem, LimitTimePurItemDetailVo.class);
                        detailVo.setItemCommission(limitTimePurItem.getDistAmount());
                        shopItemVo.setLimitTimePurItemDetailVo(detailVo);
                    }
                    shopItemVo.setAgentFlag(1); // 是代理商品
                    setItemListTag(shopItemVo);
                    return shopItemVo;
                }).collect(Collectors.toList()));
            } else {
                pageVo.setData(new ArrayList(0));
            }
            return pageVo;
        } else {
            if (!agentItemIds.isEmpty()) {
                List<Item> agentItems = itemDao.selectByPrimaryKeys(agentItemIds);
                items.addAll(0, agentItems);
            }
        }
        // 限时购
        List<String> limitTimePurItemIds = new ArrayList<>();
        List<String> itemIds = items.stream().map(item -> {
            if (BaseEnum.StatusEnum.ENABLE.getCode().equals(item.getLimitTimeFlag())) {
                limitTimePurItemIds.add(item.getId());
            }
            return item.getId();
        }).collect(Collectors.toList());
        itemIds.addAll(agentItemIds);
        Map<String, Integer> shopCartItemQtyMap;
        if (StringUtils.hasText(param.getUserId())) {
            List<ShoppingCarItemNumDto> shopCartItems = shoppingCartDao.getItemNumGroupByItem(param.getUserId(), itemIds);
            shopCartItemQtyMap = shopCartItems.stream().collect(Collectors.toMap(ShoppingCarItemNumDto::getItemId, ShoppingCarItemNumDto::getExistNum));
        } else {
            shopCartItemQtyMap = new HashMap<>(0);
        }
        Map<String, LimitTimePurItemVo> limitTimePurItemMap;
        if (!limitTimePurItemIds.isEmpty()) {
            QueryLimitTimePurGoodBo limitTimePurBo = new QueryLimitTimePurGoodBo();
            limitTimePurBo.setItemIds(limitTimePurItemIds);
            List<LimitTimePurItemVo> limitTimePurItems = limitTimePurActiveService.getGood(limitTimePurBo);
            limitTimePurItemMap = limitTimePurItems.stream().collect(Collectors.toMap(LimitTimePurItemVo::getItemId, Function.identity()));
        } else {
            limitTimePurItemMap = new HashMap<>(0);
        }
        pageVo.setData(items.stream().map(item -> {
            ShopItemListVo shopItemVo = BeanConverUtils.convertBean(item, ShopItemListVo.class, "itemCommission");
            shopItemVo.setExistCarNum(shopCartItemQtyMap.get(item.getId()));
            LimitTimePurItemVo limitTimePurItem = limitTimePurItemMap.get(item.getId());
            if (limitTimePurItem != null) {
                LimitTimePurItemDetailVo detailVo = BeanConverUtils.convertBean(limitTimePurItem, LimitTimePurItemDetailVo.class);
                detailVo.setItemCommission(limitTimePurItem.getDistAmount());
                shopItemVo.setLimitTimePurItemDetailVo(detailVo);
            }
            if (agentItemIds.contains(item.getId())) {
                shopItemVo.setAgentFlag(1); // 是代理商品
            }
            setItemListTag(shopItemVo);
            return shopItemVo;
        }).collect(Collectors.toList()));

        return pageVo;
    }

    private void setItemListTag(ShopItemListVo shopItemListVo) {
        if (StrUtil.isNotEmpty(shopItemListVo.getItemSgin())) {
            shopItemListVo.setItemListTags(Arrays.asList(shopItemListVo.getItemSgin().split(",")));
        }
    }

    private void setItemTag(ShopItemVo shopItemVo) {
        List<ItemTag> itemTags = itemTagDao.getByItemId(shopItemVo.getId());
        if (!CollectionUtils.isEmpty(itemTags)) {
            shopItemVo.setItemTagList(BeanConverUtils.convertBeanList(itemTags, ItemTagVo.class));
        }
    }

    private void setDiscountItem(List<DiscountItem> discountItems, ShopItemVo shopItemVo, String itemId) {
        if (!CollectionUtils.isEmpty(discountItems)) {
            DiscountItem di = discountItems.stream().filter(discountItem -> itemId.equals(discountItem.getItemId())).findFirst().orElse(null);
            shopItemVo.setDiscountItemVo(null != di ? BeanConverUtils.convertBean(di, DiscountItemDetailVo.class) : null);
        }
    }

    private void setShoppingCarNum(List<ShoppingCarItemNumDto> dtoList, ShopItemListVo shopItemVo, String itemId) {
        if (!CollectionUtils.isEmpty(dtoList)) {
            dtoList.forEach(scDto -> {
                if (itemId.equals(scDto.getItemId())) {
                    shopItemVo.setExistCarNum(scDto.getExistNum());
                }
            });
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void shelf(ItemShelfBo bo) {
        ParamException.isFalse(BaseEnum.StatusEnum.DISABLE.getCode().equals(bo.getItemStatus()) || BaseEnum.StatusEnum.ENABLE.getCode().equals(bo.getItemStatus()), "上下架状态值不正确");
        Item item = BeanConverUtils.convertBean(bo, Item.class, "shopId");
        itemDao.updateByPrimaryKeySelective(item);
//        updateDiscountStatus(bo.getId(),bo.getItemStatus());
        ((ShopItemService) AopContext.currentProxy()).syncSearch(bo.getId());
    }

    @Async
    public void syncSearch(String itemId) {
        doSyncSearch(itemId);
    }

    public void batchShelf(ItemBatchShelfBo bo) {
        ParamException.isFalse(BaseEnum.StatusEnum.DISABLE.getCode().equals(bo.getItemStatus()) || BaseEnum.StatusEnum.ENABLE.getCode().equals(bo.getItemStatus()), "上下架状态值不正确");
        ParamException.isTrue(!StringUtils.hasText(bo.getShopId()) || CollectionUtils.isEmpty(bo.getIds()));
        itemDao.batchShelf(bo);
        ((ShopItemService) AopContext.currentProxy()).batchSyncSearch(bo.getIds());
    }

    @Async
    public void batchSyncSearch(List<String> itemIds) {
        for (String itemId : itemIds) {
            doSyncSearch(itemId);
        }
    }

    private void doSyncSearch(String itemId) {
        ItemVo itemVo = BeanConverUtils.convertBean(itemDao.selectByPrimaryKey(itemId), ItemVo.class);
        searchApi.create(itemVo);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void delete(String id) {
        itemDao.deleteById(id);
        itemMediaDao.deleteByItem(id);
        skuDao.deleteByItemId(id);
        discountItemDao.deleteByItemId(id);
        discountItemSkuDao.deleteByItemId(id);
        itemTagDao.deleteByItemId(id);
        searchApi.delete(id);
    }

    public PageVo<ShopItemVo> page(PageBo<ShopItemPageBo> bo) {
        PageHelper.startPage(bo.getPage(), bo.getPageSize(), MySqlUtil.orderBy(bo.getSort(), bo.isAsc()));
        PageInfo<Item> pageInfo = new PageInfo<>(itemDao.geShopConsoleList(bo.getParam()));
        List<ShopItemVo> list = BeanConverUtils.convertBeanList(pageInfo.getList(), ShopItemVo.class);
        List<String> categoryIds = list.stream().map(ShopItemVo::getCategoryId).collect(Collectors.toList());
        List<Category> categories = categoryDao.selectByPrimaryKeys(categoryIds);
        list.forEach(shopItemVo -> categories.forEach(category -> {
            if (shopItemVo.getCategoryId().equals(category.getId())) {
                shopItemVo.setCategoryName(category.getName());
            }
        }));
        return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(), list);
    }

    public void sort(String itemId, Integer itemSort) {
        Item item = new Item();
        item.setId(itemId);
        item.setItemSort(itemSort);
        itemDao.updateByPrimaryKeySelective(item);
    }

    public ShopItemVo get(String id, String product) {
        ShopItemVo shopItemVo = BeanConverUtils.convertBean(itemDao.getItemDetailById(id), ShopItemVo.class, "itemCommission");
        if (null == shopItemVo) {
            return null;
        }
        setCategoryFullName(shopItemVo);
        setShopInfo(shopItemVo);
        setMedial(product, shopItemVo);
        setDiscountInfo(product, shopItemVo);
        setLimitTimePurInfo(product, shopItemVo);
        setItemTag(shopItemVo);
        shopItemVo.setGoodsProfitVo(goodsProfitService.queryGoodsProfitVoByItemId(shopItemVo.getId()));
        return shopItemVo;
    }

    private void setDiscountInfo(String product, ShopItemVo shopItemVo) {
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(shopItemVo.getDiscountFlag())) {
            DiscountItem discountItem = discountItemDao.getByItemId(shopItemVo.getId());
            if (null != discountItem) {
                List<ActiveItemSkuVo> atSKus = BeanConverUtils.convertBeanList(shopItemVo.getSkus(), ActiveItemSkuVo.class);
                fillDiscountItemSku(atSKus, discountItem);
                DiscountItemDetailVo discountItemVo = BeanConverUtils.convertBean(discountItem, DiscountItemDetailVo.class);
                discountItemVo.setSkuVoList(atSKus);
                shopItemVo.setDiscountItemVo(discountItemVo);
                updateDiscountItemViews(discountItem.getId(), discountItem.getViews());
            }
        }
    }

    private void setLimitTimePurInfo(String product, ShopItemVo shopItemVo) {
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(shopItemVo.getLimitTimeFlag())) {
            QueryLimitTimePurGoodBo limitTimePurBo = new QueryLimitTimePurGoodBo();
            limitTimePurBo.setItemId(shopItemVo.getId());
            limitTimePurBo.setIsEffect(BaseEnum.StatusEnum.ENABLE.getCode());
            //limitTimePurBo.setIsNow(Instant.now());
            List<LimitTimePurItemVo> limitTimePurItemVos = limitTimePurActiveService.getGood(limitTimePurBo);

            if (!CollectionUtils.isEmpty(limitTimePurItemVos)) {
                LimitTimePurItemVo limitTimePurItemVo = limitTimePurItemVos.get(0);
                LimitTimePurActive limitTimePurActive = limitTimePurActiveDao.selectByPrimaryKey(limitTimePurItemVo.getLimitActiveId());
                List<ActiveItemSkuVo> atSKus = BeanConverUtils.convertBeanList(shopItemVo.getSkus(), ActiveItemSkuVo.class);
                matchLimitTimePurSku(shopItemVo.getId(), atSKus);
                List<ActiveItemSkuVo> atSKusNew = new ArrayList<>(atSKus);
                ActiveItemSkuVo activeItemSkuVo = atSKusNew.stream().filter(o -> o.getItemCommission().compareTo(BigDecimal.ZERO) > 0).sorted(Comparator.comparing(ActiveItemSkuVo::getItemCommission)).findFirst().orElse(null);
                LimitTimePurItemDetailVo limitTimePurItemDetailVo = BeanConverUtils.convertBean(limitTimePurItemVo, LimitTimePurItemDetailVo.class);
                limitTimePurItemDetailVo.setSkuVoList(atSKus);
                if (null != activeItemSkuVo) {
                    shopItemVo.setItemCommission(activeItemSkuVo.getItemCommission());
                    limitTimePurItemDetailVo.setItemCommission(activeItemSkuVo.getItemCommission());
                }
                limitTimePurItemDetailVo.setStartTime(limitTimePurActive.getStartTime());
                limitTimePurItemDetailVo.setEndTime(limitTimePurActive.getEndTime());
                shopItemVo.setLimitTimePurItemDetailVo(limitTimePurItemDetailVo);
                updateLimitTimePurViews(shopItemVo.getId(), limitTimePurItemVo.getLimitActiveId());
            }
        }
    }

    private void updateLimitTimePurViews(String id, String limitActiveId) {
        limitTimePurActiveService.updateViewCount(id, limitActiveId);
    }

    private void updateDiscountItemViews(String id, Integer views) {
        DiscountItem discountItem = new DiscountItem();
        Integer increment = null == views ? 1 : views + 1;
        discountItem.setId(id);
        discountItem.setViews(increment);
        discountItemDao.updateByPrimaryKeySelective(discountItem);
    }

    private void setCategoryFullName(ShopItemVo shopItemVo) {
        Category category = categoryDao.selectByPrimaryKey(shopItemVo.getCategoryId());
        if (null != category) {
            String fullName = category.getName();
            shopItemVo.setCategoryName(fullName);
            if (StrUtil.isNotEmpty(category.getPid())) {
                Category fCategory = categoryDao.selectByPrimaryKey(category.getPid());
                if (null != fCategory) {
                    fullName = fCategory.getName() + "（" + fullName + "）";
                }
            }
            shopItemVo.setCategoryFullName(fullName);
        }
    }

    private void setShopInfo(ShopItemVo shopItemVo) {
        ShopVo shopVo = shopApi.getShopById(shopItemVo.getShopId()).getResult();
        if (null != shopVo) {
            String tel = shopVo.getConsumerServiceTel();
            if (StrUtil.isEmpty(tel)) {
                tel = shopVo.getUserTel();
            }
            shopItemVo.setShopTel(tel);
            shopItemVo.setShopStatus(shopVo.getStatus());
            shopItemVo.setSystemStop(shopVo.getSystemStop());
            shopItemVo.setDefaultShop(shopVo.getDefaultTag());
        }
    }

    private void setMedial(String product, ShopItemVo shopItemVo) {
        if (!CollectionUtils.isEmpty(shopItemVo.getMedias()) && BaseEnum.ProductEnum.SHOP_CONSOLE.getName().equals(product)) {
            for (ItemMediaVo mediaVo : shopItemVo.getMedias()) {
                if (mediaVo.getMediaType() == 1 && mediaVo.getMediaIndex() == 0) {
                    shopItemVo.setItemVideo(mediaVo.getMediaUrl());
                    shopItemVo.getMedias().remove(mediaVo);
                    break;
                }
            }
        }
    }

    private void setStock(ShopItemVo shopItemVo) {
        if (!CollectionUtils.isEmpty(shopItemVo.getSkus())) {
            AtomicInteger stock = new AtomicInteger(0);
            for (ShopItemSkuVo skuVo : shopItemVo.getSkus()) {
                if (null != skuVo.getStock()) {
                    stock.addAndGet(skuVo.getStock());
                }
            }
            shopItemVo.setStock(stock.get());
        }
    }

    public List<ActiveItemSkuVo> listSkuByItemId(String itemId) {
        List<Sku> skus = skuDao.findByItemId(itemId, BaseEnum.StatusEnum.ENABLE.getCode());
        List<ActiveItemSkuVo> list = BeanConverUtils.convertBeanList(skus, ActiveItemSkuVo.class);
        matchDiscountItemSku(itemId, list);
        matchLimitTimePurSku(itemId, list);
        return list;
    }

    private List<ActiveItemSkuVo> matchLimitTimePurSku(String itemId, List<ActiveItemSkuVo> list) {
        QueryLimitTimePurGoodBo bo = new QueryLimitTimePurGoodBo();
        bo.setItemId(itemId);
        bo.setIsEffect(BaseEnum.StatusEnum.ENABLE.getCode());
        //bo.setIsNow(Instant.now());
        List<LimitTimePurGood> limitTimePurGoods = limitTimePurGoodDao.queryGood(bo);
        if (!CollectionUtils.isEmpty(limitTimePurGoods)) {
            list.forEach(sku -> {
                LimitTimePurGood ltpGood = limitTimePurGoods.stream()
                        .filter(limitTimePurGood -> sku.getBarcode().equals(limitTimePurGood.getBarcode()) && limitTimePurGood.getLimitCount().compareTo(0) > 0)
                        .findFirst().orElse(null);
                if (sku.getItemCommission() == null) {
                    sku.setItemCommission(BigDecimal.ZERO);
                }
                if (null != ltpGood) {
                    sku.setDiscountPrice(ltpGood.getLimitPrice());
                    sku.setStock(ltpGood.getLimitCount() - ltpGood.getSaleCount());
                    sku.setItemCommission(ltpGood.getDistAmount());
                }
            });
        }
        return list;
    }

    private List<ActiveItemSkuVo> matchDiscountItemSku(String itemId, List<ActiveItemSkuVo> list) {
        DiscountItem di = discountItemDao.getByItemId(itemId);
        if (null != di) {
            fillDiscountItemSku(list, di);
        }
        return list;
    }

    private void fillDiscountItemSku(List<ActiveItemSkuVo> list, DiscountItem di) {
        List<DiscountItemSku> discountItemSkus = discountItemSkuDao.findByDiscountItemId(di.getId());
        list.forEach(sku -> {
            DiscountItemSku discountItemSku = discountItemSkus.stream()
                    .filter(disItemSku -> sku.getId().equals(disItemSku.getSkuId()) && BaseEnum.StatusEnum.ENABLE.getCode().equals(disItemSku.getSkuStatus()))
                    .findFirst().orElse(null);
            if (null != discountItemSku) {
                sku.setDiscountPrice(discountItemSku.getDiscountPrice());
                sku.setItemCommission(discountItemSku.getItemCommission());
                sku.setDiscount(discountItemSku.getDiscount());
                sku.setStock(discountItemSku.getStock());
            }
        });
    }

    public void offShelf(ItemOffShelfBo bo, String userId) {
        Item item = BeanConverUtils.convertBean(bo, Item.class);
        item.setItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        itemDao.updateByPrimaryKeySelective(item);
//        updateDiscountStatus(bo.getId(),BaseEnum.StatusEnum.DISABLE.getCode());
        ((ShopItemService) AopContext.currentProxy()).pushMessageToShop(bo.getId(), bo.getShelfReason(), userId);
    }

    @Async
    public void pushMessageToShop(String itemId, String messageText, String userId) {
        Item entity = itemDao.selectByPrimaryKey(itemId);
        if (null != entity) {
            ShopMessageBo smb = new ShopMessageBo();
            smb.setShopId(entity.getShopId());
            smb.setTitle("违规商品下架通知");
            smb.setMessageAbstract("违规商品下架通知");
            smb.setText(messageText);
            smb.setPushTime(Instant.now());
            smb.setType(MessageReceiveTypeEnum.SHOP.getCode());
            smb.setOperator(userId);
            smb.setOperatorUpdate(userId);
            messageApi.pushMessageToShop(smb);
        }
    }

    public PageVo<MerchantShopItemPageVo> pageForMerchant(PageBo<MerchantShopItemPageBo> bo) {
        Item item = BeanConverUtils.convertBean(bo.getParam(), Item.class);
        PageHelper.startPage(bo.getPage(), bo.getPageSize(), MySqlUtil.orderBy(bo.getSort(), bo.isAsc()));
        PageInfo<Item> pageInfo = new PageInfo<>(itemDao.listForMerchant(item));
        List<MerchantShopItemPageVo> list = BeanConverUtils.convertBeanList(pageInfo.getList(), MerchantShopItemPageVo.class);
        if (CollectionUtils.isEmpty(list)) {
            return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(), list);
        }
        List<String> itemIds = list.stream().map(MerchantShopItemPageVo::getId).collect(Collectors.toList());
        List<Sku> skuList = skuDao.queryItemsSku(itemIds);
        for (MerchantShopItemPageVo shopItemVo : list) {
            setSkuInfo(skuList, shopItemVo);
        }
        return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(), list);
    }

    private void setSkuInfo(List<Sku> skuList, MerchantShopItemPageVo shopItemVo) {
        List<ShopItemSkuVo> skuVos = new ArrayList<>();
        skuList.forEach(sku -> {
            if (shopItemVo.getId().equals(sku.getItemId())) {
                skuVos.add(BeanConverUtils.convertBean(sku, ShopItemSkuVo.class));
            }
        });
        shopItemVo.setSkuList(skuVos);
    }

    public void addForMerchant(MerchantShopItemAddBo bo) {
        ParamException.isTrue((null != bo.getItemCommission() && bo.getItemCommission().compareTo(bo.getRetailPrice()) > 0), "分佣金额不能大于实际售价");
        ShopVo shop = getShopById(bo.getShopId());
        ShopItemAddBo addBo = BeanConverUtils.convertBean(bo, ShopItemAddBo.class);
        addBo.setShopId(shop.getId());
        addBo.setShopName(shop.getName());
        if (null != bo.getItemCommission()) {
            SetGoodsProfitBo profitBo = new SetGoodsProfitBo();
            profitBo.setProfitType(Constant.PROFIT_GD);
            profitBo.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
            profitBo.setRatio(bo.getItemCommission());
            addBo.setGoodsProfitBo(profitBo);
        }
        createShopItem(addBo);
    }

    public void updateForMerchant(MerchantShopItemUpdateBo bo) {
        ParamException.isTrue((null != bo.getItemCommission() && bo.getItemCommission().compareTo(bo.getRetailPrice()) > 0), "分佣金额不能大于实际售价");
        ShopItemUpdateBo updateBo = BeanConverUtils.convertBean(bo, ShopItemUpdateBo.class);
        if (null != bo.getItemCommission()) {
            SetGoodsProfitBo profitBo = new SetGoodsProfitBo();
            profitBo.setProfitType(Constant.PROFIT_GD);
            profitBo.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
            profitBo.setRatio(bo.getItemCommission());
            updateBo.setGoodsProfitBo(profitBo);
        }
        updateShopItem(updateBo);
    }

    private ShopVo getShopById(String shopId) {
        return shopApi.getShopById(shopId).getResult();
    }

    public List<ShopItemVo> listHot(String shopId) {
        Item entity = new Item();
        entity.setShopId(shopId);
        entity.setItemStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        entity.setHotFlag(BaseEnum.StatusEnum.ENABLE.getCode());
        return BeanConverUtils.convertBeanList(itemDao.listHost(entity), ShopItemVo.class);
    }

    public PageVo<DiscountItemSelectPageVo> discountItemSelectPage(PageBo<DiscountItemSelectPageBo> bo) {
        PageHelper.startPage(bo.getPage(), bo.getPageSize(), MySqlUtil.orderBy(bo.getSort(), bo.isAsc()));
        PageInfo<Item> pageInfo = new PageInfo<>(itemDao.discountItemSelectList(bo.getParam()));
        List<DiscountItemSelectPageVo> list = BeanConverUtils.convertBeanList(pageInfo.getList(), DiscountItemSelectPageVo.class);
        if (CollectionUtils.isEmpty(list)) {
            return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(), list);
        }
        List<String> itemIds = list.stream().map(DiscountItemSelectPageVo::getId).collect(Collectors.toList());
        List<Sku> skuList = skuDao.queryItemsSku(itemIds);
        for (DiscountItemSelectPageVo selectPageVo : list) {
            List<Sku> selectSkuList = skuList.stream().filter(sku -> selectPageVo.getId().equals(sku.getItemId())).collect(Collectors.toList());
            selectPageVo.setSkus(BeanConverUtils.convertBeanList(selectSkuList, SkuVo.class));
        }
        return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(), list);
    }

    public DiscountItemSelectVo discountItemSelect(String itemId) {
        Item item = itemDao.selectByPrimaryKey(itemId);
        DiscountItemSelectVo disVo = BeanConverUtils.convertBean(item, DiscountItemSelectVo.class);
        List<Sku> skuList = skuDao.findByItemId(itemId, BaseEnum.StatusEnum.ENABLE.getCode());
        disVo.setSkus(BeanConverUtils.convertBeanList(skuList, SkuVo.class));
        return disVo;
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchAddDiscountItem(DiscountItemBatchAddBo addBo) {
        addBo.getDiscountItemAddBoList().forEach(bo -> addDiscountItem(bo));
    }

    @Transactional(rollbackFor = Exception.class)
    public void addDiscountItem(DiscountItemAddBo bo) {
        String itemId = bo.getItemId();
        Item item = itemDao.selectByPrimaryKey(itemId);
        ParamException.isNull(item, "商品信息异常");
        ParamException.isTrue((BaseEnum.StatusEnum.ENABLE.getCode().equals(item.getDiscountFlag()) || BaseEnum.StatusEnum.ENABLE.getCode().equals(item.getLimitTimeFlag())), "该商品已经在活动中");
        saveDiscountItem(bo, item);
        saveItemDiscountTag(itemId);
        updateItemDiscountInfo(itemId, BaseEnum.StatusEnum.ENABLE.getCode(), bo.getDiscountPrice(), bo.getItemCommission());
    }

    public void updateDiscountItem(DiscountItemUpdateBo bo) {
        ParamException.isTrue(checkDuplication(bo.getItemId(), bo.getId()), "该商品已在打折中");
        DiscountItem discountItem = BeanConverUtils.convertBean(bo, DiscountItem.class);
        discountItemDao.updateByPrimaryKeySelective(discountItem);
    }

    public PageVo<DiscountItemPageVo> pageDiscountItem(PageBo<DiscountItemPageBo> bo) {
        PageHelper.startPage(bo.getPage(), bo.getPageSize());
        PageInfo<DiscountItemPageVo> pageInfo = new PageInfo<>(discountItemDao.getDiscountItemList(bo.getParam()));
        return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(), pageInfo.getList());
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteDiscountItem(String id) {
        DiscountItem exist = discountItemDao.selectByPrimaryKey(id);
        ParamException.isNull(exist);
        DiscountItem di = new DiscountItem();
        di.setId(id);
        di.setStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        discountItemDao.updateByPrimaryKeySelective(di);
        discountItemSkuDao.updateDiscountItemSkuStatus(exist.getId(), BaseEnum.StatusEnum.DISABLE.getCode());
        deleteDiscountTag(exist.getItemId());
        List<Sku> skus = skuDao.findByItemId(exist.getItemId(), BaseEnum.StatusEnum.ENABLE.getCode());
        Sku sku = skus.stream().min(Comparator.comparing(Sku::getRetailPrice)).get();
        updateItemDiscountInfo(exist.getItemId(), BaseEnum.StatusEnum.DISABLE.getCode(), sku.getRetailPrice(), sku.getItemCommission());
    }

    private List<DiscountItemSku> fillDiscountItemSku(DiscountItem discountItem, List<DiscountItemSkuBo> skuBoList) {
        List<DiscountItemSku> list = BeanConverUtils.convertBeanList(skuBoList, DiscountItemSku.class);
        AtomicInteger stock = new AtomicInteger(0);
        list.forEach(discountItemSku -> {
            stock.addAndGet(discountItemSku.getStock());
            discountItemSku.setDiscountItemId(discountItem.getId());
            discountItemSku.setSkuStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        });
        discountItem.setStock(stock.get());
        return list;
    }

    private void saveDiscountItem(DiscountItemAddBo bo, Item item) {
        DiscountItem discountItem = BeanConverUtils.convertBean(bo, DiscountItem.class);
        discountItem.setId(UUIDGenerator.getShortUUID());
        discountItem.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        discountItem.setSales(0);
        discountItem.setOrderNum(0);
        discountItem.setOrderAmount(BigDecimal.ZERO);
        discountItem.setViews(0);
        saveDiscountItemSkuList(bo.getSkuBoList(), item, discountItem);
        discountItemDao.insert(discountItem);
    }

    private void saveDiscountItemSkuList(List<DiscountItemSkuBo> skuBoList, Item item, DiscountItem discountItem) {
        List<DiscountItemSku> list = fillDiscountItemSku(discountItem, skuBoList);
        ParamException.isTrue(discountItem.getStock().compareTo(item.getStock()) > 0, "商品打折库存不能大于商品本身库存");
        discountItemSkuDao.insertList(list);
    }

    private String getItemTagString(String itemId) {
        List<ItemTag> list = itemTagDao.getByItemId(itemId);
        StringJoiner sj = new StringJoiner(",");
        list.forEach(itemTag -> {
            sj.add(itemTag.getName());
        });
        return sj.toString();
    }

    private void saveItemDiscountTag(String itemId) {
        ItemTag it = new ItemTag();
        it.setItemId(itemId);
        it.setName(GoodsEnum.ItemTagEnum.DISCOUNT.getName());
        it.setCode(GoodsEnum.ItemTagEnum.DISCOUNT.getCode());
        itemTagDao.insert(it);
    }

    private void updateItemDiscountInfo(String itemId, Integer discountFlag, BigDecimal price, BigDecimal commission) {
        String tagStr = getItemTagString(itemId);
        Item update = new Item();
        update.setId(itemId);
        update.setItemSgin(null == tagStr ? "" : tagStr);
        update.setDiscountFlag(discountFlag);
        update.setOriginPrice(price);
        update.setItemCommission(null == commission ? BigDecimal.ZERO : commission);
        itemDao.updateByPrimaryKeySelective(update);
    }

    private void deleteDiscountTag(String itemId) {
        itemTagDao.deleteByItemIdAndCode(itemId, GoodsEnum.ItemTagEnum.DISCOUNT.getCode());
    }

    private Boolean checkDuplication(String itemId, String id) {
        List<DiscountItem> list = discountItemDao.getDuplicationDiscountItem(itemId, id);
        return !CollectionUtils.isEmpty(list);
    }

    public PageVo<AgentItemPageVo> agentItemPage(PageBo<AgentItemPageBo> pageBo) {
        AgentItemPageBo param = pageBo.getParam();
        ShopVo shopVo = shopApi.checkMemberShop(param.getAgentShopId(), param.getCurrentShopId()).getResult();
        IllegalException.isNull(shopVo, "您无权操作该店铺数据");
        String userShopId = shopVo.getId();
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        PageInfo<Item> pageInfo = new PageInfo<>(itemDao.findAgentItemList(pageBo.getParam()));
        List<Item> items = pageInfo.getList();
        List<AgentItemPageVo> list = BeanConverUtils.convertBeanList(items, AgentItemPageVo.class);
        if (CollectionUtils.isEmpty(list)) {
            return new PageVo<>(pageInfo.getTotal(), pageBo.getPage(), pageBo.getPageSize(), list);
        }
        List<String> barcodes = items.stream().map(Item::getBarcode).collect(Collectors.toList());
        List<Item> copyItems = itemDao.getAgencyItemList(userShopId, barcodes);
        list.forEach(itemPageVo -> {
            for (Item item : copyItems) {
                if (StrUtil.isNotEmpty(itemPageVo.getBarcode()) && itemPageVo.getBarcode().equals(item.getAgencyItemCode())) {
                    itemPageVo.setCopied(BaseEnum.StatusEnum.ENABLE.getCode());
                    break;
                }
            }
        });
        return new PageVo<>(pageInfo.getTotal(), pageBo.getPage(), pageBo.getPageSize(), list);
    }

    public void copyAgentItem(AgentItemCopyBo bo) {
        ShopVo shopVo = shopApi.checkMemberShop(bo.getAgentShopId(), bo.getCurrentShopId()).getResult();
        IllegalException.isNull(shopVo, "您无权操作该店铺数据");
        String userShopId = shopVo.getId();
        String shopName = shopVo.getName();
        List<String> itemIds = bo.getItemIds();
        Category category = getDefaultCategory(userShopId);
        List<Item> items = itemDao.selectByPrimaryKeys(itemIds);
        ParamException.isTrue(CollectionUtils.isEmpty(items), "复制的商品不存在");
        List<Sku> skus = skuDao.findByItemIds(itemIds, BaseEnum.StatusEnum.ENABLE.getCode());
        ParamException.isTrue(CollectionUtils.isEmpty(skus), "复制的商品规格信息不存在");
        List<ItemMedia> medias = itemMediaDao.findByItemIds(itemIds);
        ParamException.isTrue(CollectionUtils.isEmpty(medias), "复制的商品图片信息不存在");

        items.forEach(item -> {
            String itemId = UUIDGenerator.getShortUUID();
            skus.forEach(sku -> {
                fillSku(item, itemId, sku);
            });
            medias.forEach(media -> {
                fillMedia(item, itemId, media);
            });
            fillItem(userShopId, shopName, category, item, itemId);
        });
        itemDao.insertList(items);
        skuDao.insertList(skus);
        itemMediaDao.insertList(medias);
    }

    private void fillSku(Item item, String itemId, Sku sku) {
        if (item.getId().equals(sku.getItemId())) {
            sku.setBarcode(RandomUtil.randomString(RandomUtil.BASE_CHAR, 4).toUpperCase() + RandomUtil.randomNumbers(5));
            sku.setItemCommission(BigDecimal.ZERO);
            sku.setItemId(itemId);
            sku.setId(UUIDGenerator.getShortUUID());
        }
    }

    private void fillMedia(Item item, String itemId, ItemMedia media) {
        if (item.getId().equals(media.getItemId())) {
            media.setItemId(itemId);
            media.setId(UUIDGenerator.getShortUUID());
        }
    }

    private void fillItem(String userShopId, String shopName, Category category, Item item, String itemId) {
        item.setId(itemId);
        item.setAgencyItemCode(item.getBarcode());
        item.setItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        item.setShopId(userShopId);
        item.setShopName(shopName);
        item.setCategoryId(category.getId());
        item.setCategoryCode(category.getCategoryCode());
        item.setBarcode(RandomUtil.randomString(RandomUtil.BASE_CHAR, 5).toUpperCase() + RandomUtil.randomNumbers(6));
        item.setAgencyFlag(BaseEnum.StatusEnum.ENABLE.getCode());
        item.setItemCommission(BigDecimal.ZERO);
        item.setActivitySgin(null);
        item.setItemSgin(null);
        item.setFalseSales(0);
        item.setSales(0);
        item.setSumSales(0);
        item.setHotFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        item.setDiscountFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        //是否限时购
        item.setLimitTimeFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        //是否限购
        item.setLimitFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        item.setLimitQuantity(null);
        item.setShelfReason(null);
        item.setItemType(GoodsEnum.CategoryTypeEnum.RETAIL.getCode());
    }

    private Category getDefaultCategory(String shopId) {
        Category category = new Category();
        category.setShopId(shopId);
        category.setName("其它");
        Category exist = categoryDao.selectOne(category);
        if (null != exist) {
            return exist;
        }
        category.setId(UUIDGenerator.getShortUUID());
        category.setCategoryCode(category.getId());
        category.setCategoryType(GoodsEnum.CategoryTypeEnum.RETAIL.getCode());
        category.setEffect(BaseEnum.StatusEnum.ENABLE.getCode());
        category.setSort(99);
        categoryDao.insert(category);
        return category;
    }

}
